using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.Drawing;
using System.Text;
using System.Windows.Forms;
using System.Net;
using System.IO;
using System.Xml.Serialization;

namespace Fingerpori
{
    public partial class MainForm : Form
    {
        public delegate void StringParameterHandler(List<string> paramters);

        #region Constants
        private const int MARGIN_SIZE = 25;
        private const string BASE_ADDRESS = "http://www.hs.fi/fingerpori/";
        private const string DECRYPTCODE = "SDFAsv#54dfsvzxcESESD";
        private const string PLAIN_SETTINGS_FILE = "settings.xml";
        private const string DECRYPT_FILE = "settings.dat";
        private const Int32 WM_SYSCOMMAND = 0x112;
        private const Int32 MF_BYPOSITION = 0x400;
        private const Int32 ABOUTMENU = 1000;
        #endregion

        #region Private members
        private Image m_currentImage;
        private Image m_newImage;
        private string m_current_url = BASE_ADDRESS;
        private static Settings m_settings;
        #endregion

        #region Constructor
        public MainForm()
        {
            InitializeComponent();

            m_settings = new Settings();
            LoadSettings();

            DateTime today = new DateTime(DateTime.Now.Year, DateTime.Now.Month, DateTime.Now.Day);
            this.Text = "Fingerpori " + GetStripDate(BASE_ADDRESS).ToShortDateString();

            this.MouseDoubleClick += new MouseEventHandler(MainForm_MouseDoubleClick);
            this.MouseClick += new MouseEventHandler(MainForm_MouseDoubleClick);
          
            ResizeRedraw = true;
            SetLoadLabel(true);
            LoadCurrent();            
        }
        #endregion

        #region Overridden operations
        protected override void OnPaint(PaintEventArgs pea)
        {
            try
            {
                Point panelLoc = new Point(MARGIN_SIZE, MARGIN_SIZE);
                pictureBox.Location = panelLoc;

                this.Width = m_currentImage.Width + (2 * MARGIN_SIZE);
                this.Height = m_currentImage.Height + (4 * MARGIN_SIZE);
            }
            catch (Exception)
            {
            }
        }

        protected override void WndProc(ref Message msg)
        {
            if (msg.Msg == WM_SYSCOMMAND)
            {
                switch (msg.WParam.ToInt32())
                {
                    case ABOUTMENU:
                        using (AboutBox ab = new AboutBox(
                            m_settings.Proxy,
                            m_settings.ProxyPort.ToString(),
                            m_settings.ProxyUsername,
                            m_settings.ProxyPassword))
                        {
                            ab.StringParameterCallback = new StringParameterHandler(this.UpdateSettings);
                            ab.StartPosition = FormStartPosition.CenterParent;
                            ab.ShowDialog();
                        }
                        return;
                    default:
                        break;
                }
            }
            base.WndProc(ref msg);
        }
        #endregion

        #region Events
        private void linkLabel_LinkClicked(object sender, LinkLabelLinkClickedEventArgs e)
        {
            using (AboutBox ab = new AboutBox(
                m_settings.Proxy,
                m_settings.ProxyPort.ToString(),
                m_settings.ProxyUsername,
                m_settings.ProxyPassword))
            {
                ab.StringParameterCallback = new StringParameterHandler(this.UpdateSettings);
                ab.StartPosition = FormStartPosition.CenterParent;
                ab.ShowDialog();
            }
        }

        void MainForm_MouseDoubleClick(object sender, MouseEventArgs e)
        {
            blendTimer.Start();
            int x = e.Location.X;
            if (x < this.Width / 2) LoadPrevious();
            else LoadNext();
        }

        private void MainForm_Load(object sender, EventArgs e)
        {
            IntPtr MenuHandle = GeneralUtilities.NativeMethods.GetSystemMenu(this.Handle, false);
            GeneralUtilities.NativeMethods.InsertMenu(MenuHandle, 5, MF_BYPOSITION, ABOUTMENU, "About...");
        }

        private void blendTimer_Tick(object sender, EventArgs e)
        {
        }

        private void blendPanel_MouseHover(object sender, EventArgs e)
        {
            toolTip.ShowAlways = true;
            toolTip.ReshowDelay = 100;
            toolTip.UseAnimation = true;

            if (Control.MousePosition.X < this.Width / 2)
                toolTip.Show("Click for previous strip", this);
            else
                toolTip.Show("Click for next strip", this);
        }

        private void MainForm_FormClosed(object sender, FormClosedEventArgs e)
        {
            FileStream stream = null;
            XmlSerializer s = null;

            m_settings.ProxyPassword = GeneralUtilities.EncDec.Encrypt(m_settings.ProxyPassword, DECRYPTCODE);

            try
            {
                stream = new FileStream(PLAIN_SETTINGS_FILE, FileMode.Create, FileAccess.Write);
                s = new XmlSerializer(m_settings.GetType());
                s.Serialize(stream, m_settings);
            }
            catch (Exception ex)
            {
#if DEBUG
                MessageBox.Show(ex.Message.ToString(), "Error", MessageBoxButtons.OK, MessageBoxIcon.Error);
#endif
            }
            finally
            {
                if (stream != null)
                {
                    stream.Close();
                }
            }
        }
        #endregion

        #region Public operations
        public void UpdateSettings(List<string> p_settings)
        {
            int index = 0;
            try
            {
                m_settings.Proxy = p_settings[index++];
                m_settings.ProxyPort = Convert.ToInt16(p_settings[index++]);
                m_settings.ProxyUsername = p_settings[index++];
                m_settings.ProxyPassword = p_settings[index++];
                LoadCurrent();
                this.Invalidate();
                this.Update();
                Application.DoEvents();

            }
            catch (Exception e)
            {
                // TODO
            }
        }
        #endregion

        #region Private operations
        private void SetLoadLabel(bool p_visible)
        {
            Point loc = new Point((this.Width / 2) - (loadLabel.Width / 2), (this.Height / 2) - (loadLabel.Height / 2));
            loadLabel.Location = loc;

            if (p_visible == true)
                loadLabel.Show();
            else
                loadLabel.Hide();
        }

        private DateTime GetStripDate(string p_url)
        {
            int index1 = 0, index2 = 0, index3 = 0;
            string startLocation = "<h1>Fingerpori</h1>";

            string pageSource = GeneralUtilities.Networking.GetPageSource(
                p_url,
                m_settings.ProxyUsername,
                m_settings.ProxyPassword,
                m_settings.Proxy,
                m_settings.ProxyPort);

            try
            {
                index1 = pageSource.IndexOf(startLocation, 0);
                index2 = index1 + startLocation.Length + 4;
                index3 = pageSource.IndexOf("</p>", index2);

                string dateString = pageSource.Substring(index2, index3 - index2);

                return Convert.ToDateTime(dateString);
            }
            catch (Exception)
            {
                return DateTime.Today;
            }
        }

        private void LoadCurrent()
        {
            m_currentImage = GeneralUtilities.Networking.LoadImage(
                GetStripAddress(BASE_ADDRESS),
                m_settings.ProxyUsername,
                m_settings.ProxyPassword,
                m_settings.Proxy,
                m_settings.ProxyPort);

            if (m_currentImage != null)
            {
                pictureBox.Image = m_currentImage;
                pictureBox.Size = m_currentImage.Size;
            }

            Point labelLoc = new Point((this.Width / 2) - (linkLabel.Width / 2), (this.Height / 2) - (linkLabel.Height / 2));
            linkLabel.Location = labelLoc;

            if (m_currentImage != null)
            {
                linkLabel.Hide();
                SetLoadLabel(false);
            }
            else
            {
                linkLabel.Show();
                SetLoadLabel(false);
            }
        }

        private void LoadPrevious()
        {
            string url = string.Empty;
            string pageSource = GeneralUtilities.Networking.GetPageSource(
                m_current_url,
                m_settings.ProxyUsername,
                m_settings.ProxyPassword,
                m_settings.Proxy,
                m_settings.ProxyPort);
            int index2 = 0, index3 = 0, index4 = 0;

            if (!string.IsNullOrEmpty(pageSource))
            {
                index2 = pageSource.IndexOf("Edellinen", 0);
                if (index2 != -1) index3 = pageSource.IndexOf("href=\"", index2 - 100);
                if (index3 != -1) index4 = pageSource.IndexOf("\"", index3 + 6);
                if (index4 != -1) url = pageSource.Substring(index3 + 6, index4 - index3 - 6);

                if (url.StartsWith("http://", StringComparison.OrdinalIgnoreCase))
                {
                    m_current_url = url;
                    m_newImage = GeneralUtilities.Networking.LoadImage(
                        GetStripAddress(url),
                        m_settings.ProxyUsername,
                        m_settings.ProxyPassword,
                        m_settings.Proxy,
                        m_settings.ProxyPort);
                }

                if (m_newImage != null)
                {
                    pictureBox.Image = m_newImage;
                    pictureBox.Size = m_newImage.Size;
                    SetLoadLabel(false);
                }
            }
            this.Refresh();
        }

        private void LoadNext()
        {
            string url = string.Empty;
            string pageSource = GeneralUtilities.Networking.GetPageSource(
                m_current_url,
                m_settings.ProxyUsername,
                m_settings.ProxyPassword,
                m_settings.Proxy,
                m_settings.ProxyPort);
            int index2 = 0, index3 = 0, index4 = 0;

            if (!string.IsNullOrEmpty(pageSource))
            {
                index2 = pageSource.IndexOf("Seuraava", 0);
                if (index2 != -1) index3 = pageSource.IndexOf("href=\"", index2 - 100);
                if (index3 != -1) index4 = pageSource.IndexOf("\"", index3 + 6);
                if (index4 != -1) url = pageSource.Substring(index3 + 6, index4 - index3 - 6);

                if (url.StartsWith("http://", StringComparison.OrdinalIgnoreCase))
                {
                    m_current_url = url;
                    m_newImage = GeneralUtilities.Networking.LoadImage(
                        GetStripAddress(url),
                        m_settings.ProxyUsername,
                        m_settings.ProxyPassword,
                        m_settings.Proxy,
                        m_settings.ProxyPort);
                }

                if (m_newImage != null)
                {
                    pictureBox.Image = m_newImage;
                    pictureBox.Size = m_newImage.Size;
                    SetLoadLabel(false);
                }
            }
            this.Refresh();
        }

        private string GetStripAddress(string p_url)
        {
            string address = string.Empty;
            string pageSource = GeneralUtilities.Networking.GetPageSource(
                p_url,
                m_settings.ProxyUsername,
                m_settings.ProxyPassword,
                m_settings.Proxy,
                m_settings.ProxyPort);

            if (!string.IsNullOrEmpty(pageSource))
            {
                int index2 = 0, index3 = 0, index4 = 0;

                try
                {
                    index2 = pageSource.IndexOf("<div class=\"strip\" style=\"display: block;\">", 0);
                    if (index2 != -1) index3 = pageSource.IndexOf("src=\"", index2);
                    if (index3 != -1) index4 = pageSource.IndexOf("\"", index3 + 5);
                    if (index4 != -1) address = pageSource.Substring(index3 + 5, index4 - index3 - 5);
                }
                catch (Exception)
                {
                }
            }

            return address;
        }

        private void LoadSettings()
        {
            try
            {
                using (FileStream fs = new FileStream(PLAIN_SETTINGS_FILE, FileMode.Open, FileAccess.Read))
                {
                    XmlSerializer s = null;
                    s = new XmlSerializer(m_settings.GetType());
                    m_settings = (Settings)s.Deserialize(fs);
                    m_settings.ProxyPassword = GeneralUtilities.EncDec.Decrypt(m_settings.ProxyPassword, DECRYPTCODE);
                }
            }
            catch (Exception ex)
            {
#if DEBUG
                MessageBox.Show(ex.Message.ToString(), "Error", MessageBoxButtons.OK, MessageBoxIcon.Error);
#endif
            }
        }
        #endregion
    }
}